//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//	bssdbase.c
//		manage BSS descriptor data base
//	history :
//
//	Description:
//		BSS descriptor data base will store the information of the stations at the
//		surrounding environment. The first entry( psBSS(0) ) will not be used and the
//		second one( psBSS(1) ) will be used for the broadcast address.
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++


#include "os_common.h"
//#include "sme.h"	// use SME state defines

USHORT GetElement( PWB32_ADAPTER Adapter, USHORT wBssIdx, UCHAR * ElementAddr, USHORT Idx );


//======================  Rate conversion table  ==========================
static const UCHAR Bitmap2RateValue[32] =
{	0,					// BIT 0
	RATE_1M, 			// BIT 1
	RATE_2M, 			// BIT 2
	0,					// BIT 3
	0,					// BIT 4
	RATE_5dot5M, 		// BIT 5
	RATE_6M,			// BIT 6
	0,					// BIT 7
	0,					// BIT 8
	RATE_9M,			// BIT 9
	0,					// BIT 10
	RATE_11M,			// BIT 11
	RATE_12M,			// BIT 12
	0,					// BIT 13
	0,					// BIT 14
	0,					// BIT 15
	0,					// BIT 16
	RATE_33M,			// BIT 17
	RATE_18M,			// BIT 18
	RATE_36M,			// BIT 19
	0,					// BIT 20
	0,					// BIT 21
	RATE_22M,			// BIT 22
	0,					// BIT 23
	RATE_24M,			// BIT 24
	RATE_48M,			// BIT 25
	0,					// BIT 26
	0,					// BIT 27
	RATE_54M,			// BIT 28
	0,					// BIT 29
	0,					// BIT 30
	0,					// BIT 31
};
//#endif

void vBSSdescriptionInit(PWB32_ADAPTER Adapter)
{
	USHORT i;

	for (i = 0; i < MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		psBSS(i)->SlotValid = 0;
		MLME_initState(psBSS(i));	// MLME: INACTIVE;
		psBSS(i)->wIndex = i;
		psBSS(i)->psAdapter = Adapter;
		//The other fields will be updated when receiving beacon or probe
		//response except to the following fields:
		psBSS(i)->wAuthAlgo = OPEN_AUTH;	//default value: OPEN_AUTH = 0
		psBSS(i)->wAuthSeqNum = 0;
	}
	//entry 1 is reserved for broadcast address
	psBSS(1)->SlotValid = 1;
	OS_MEMORY_COPY( psBSS(1)->abPeerAddress, "\xff\xff\xff\xff\xff\xff", MAC_ADDR_LENGTH );
	//MLME_findSTA(psBSS(1));
}

//search valid BSS descriptors at the surrounding environment
void vBSSfoundList(PWB32_ADAPTER Adapter)
{
	USHORT i,j;
/*	UCHAR	ChanLimit;

	//
	switch (psLOCAL->region)
	{
		case REGION_EUROPE:
			ChanLimit = 13;
			break;
		case REGION_JAPAN:
		case REGION_UNKNOWN:
			ChanLimit = 14;
			break;
		case REGION_USA:
		default:
			ChanLimit = 11;
			break;
	}
*/

	j=0;
	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if (i == psLOCAL->wConnectedSTAindex)//imply psLOCAL->wConnectedSTAindex != 0
		{
			if (psBSS(psLOCAL->wConnectedSTAindex)->bBssType == IBSS_NET)
				continue;//This descirptor is for local used, not from surrounding environment
		}
		if (0 == psLOCAL->wConnectedSTAindex)
		{
			if ((i == psSME->wDesiredJoinBSS ) &&//imply psSME->wDesiredJoinBSS != 0
				(psBSS(psSME->wDesiredJoinBSS)->bBssType == IBSS_NET))
				continue;	//For local used
		}
		if (boMLME_FoundSTAinfo(psBSS(i)))
		{
			//filter 2.4G channel based on the region
			if (psBSS(i)->band == BAND_TYPE_OFDM_24)
			{
				//if (psBSS(i)->DS_Parameter_Set.Current_Channel > ChanLimit)
				//	continue;

				if (boChanFilter(Adapter, psBSS(i)->DS_Parameter_Set.Current_Channel))
					continue;
			}
			psLOCAL->BssListIndex[j]=(UCHAR)i;
			j++;
		}
	}
	psLOCAL->BssListCount = (UCHAR)j;
}

UCHAR boChanFilter(PWB32_ADAPTER Adapter, UCHAR ChanNo)
{
	UCHAR	boFilter = FALSE;

	switch (psLOCAL->region)
	{
		case REGION_EUROPE:
			if (ChanNo > 13)
				boFilter = TRUE;
			break;
		case REGION_JAPAN:
		case REGION_UNKNOWN:
			break;
		case REGION_FRANCE:
			if ((ChanNo < 10) || (ChanNo > 13))
				boFilter = TRUE;
			break;
		case REGION_SPAIN:
			if ((ChanNo < 10) || (ChanNo > 11))
				boFilter = TRUE;
			break;
		case REGION_ISRAEL:
			if ((ChanNo < 3) || (ChanNo > 9))
				boFilter = TRUE;
			break;
		case REGION_USA:
		default:
			if (ChanNo > 11)
				boFilter = TRUE;
			break;
	}
	return boFilter;
}

//Get an empty BSS descriptor entry
USHORT wBSSGetEntry(PWB32_ADAPTER Adapter)
{
	USHORT i, ret=0;

	OS_SPIN_LOCK_ACQUIRED( &Adapter->sMlmeFrame.MLMESpinLock );
	//Phase 1
	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if (psBSS(i)->SlotValid != 1) //
		{
			psBSS(i)->SlotValid = 1;
			ret = i;
			break;
		}
	}
	//Phase 2
	//=> BSS descriptor is allocated due to the frame receiving.
	//	The frame may be beacon/probe resp. or others(data frame, meaningless
	//	frame..). So if it is allocated due to not beacon/probe/resp. frame,
	//	we will reuse it.
	if (0 == ret)
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("BSS descriptor allocated phase 2\n"));
		#endif
		for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
		{
			//Check BSSID
			//if ((0 == ((PMACADDR)psBSS(i)->abBssID)->ll) &&
			//	(0 == ((PMACADDR)psBSS(i)->abBssID)->ss))
			if (!boMLME_FoundSTAinfo(psBSS(i)))
			{
				ret = i;
				break;
			}
		}
	}
	OS_SPIN_LOCK_RELEASED( &Adapter->sMlmeFrame.MLMESpinLock );
	if (ret == 0)
	{
		FillEventLog(Adapter, EVENT_BSS_DESCRIPT_LACK);
	}
	return ret;
}

#define PHASE_OUT_TIMER			1000
//============================================================================
// vSimpleHouseKeeping --
//
// Description:
//		When receiving a SCAN_REQ msg in SCAN module, set the BSS descriptor entries
//	 except to the psLOCAL->wConnectedSTAindex one to INACTIVE state if
//	 psSCAN->boSave is FALSE.
//	 (1)Set psSCAN->boSave to TRUE when receiving SCAN_REQ from ROAM module
//	 (2)
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//
//============================================================================
void vSimpleHouseKeeping(PWB32_ADAPTER Adapter)
{
	USHORT i;

	if (!psSCAN->boSave)
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("Simple HouseKeeping\n"));
		#endif
		for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
		{
			//TODO: 12/03/03'
			if (i != psLOCAL->wConnectedSTAindex)
			{
				if (!boMLME_InactiveState(psBSS(i)))
					//MLME_initState(psBSS(i));
					ClearBSSdescpt(Adapter, i);
			}
		}
		psSCAN->boSave = TRUE;
	}
}

USHORT wBSShouseKeeping(PWB32_ADAPTER Adapter)
{
	int i, iAvailable;

	iAvailable=0;
	// Rule1: all STAs in [IDLE_SCAN] and didn't update for a PHASE_OUT time
	for (i=0;i<MAX_BSS_DESCRIPT_ELEMENT;i++)
	{
		if (boMLME_IdleScanState(psBSS(i))) //->wState==IDLE_SCAN)
		{
			//if ((HWLocalTime-psBSS(i)->dwLocalTime)>PHASE_OUT_TIMER) 
			//{	
			//	MLME_initState(psBSS(i)); // MLME: INACTIVE
			//  iAvailable=i+1;
			//}
		}
	}
	if (iAvailable!=0)	return (USHORT)(iAvailable);
	// Rule2: all STAs didn't update for a PHASE_OUT time and its BSSID and SSID are not currently used
	for (i=0;i<MAX_BSS_DESCRIPT_ELEMENT;i++)
	{
		//if ((HWLocalTime-psBSS(i)->dwLocalTime)>PHASE_OUT_TIMER)
		//{
		//	if 	(boCmpMacAddr(psBSS(i)->abBssID,local->BSSID)
		//	{
		//		MLME_initState(psBSS(i));
		//		iAvailable=i+1;
		//	}
		//}
	}
	return (USHORT)(iAvailable);
}

//clear the content of some elements in this bss descriptor
void ClearBSSdescpt(PWB32_ADAPTER Adapter, USHORT i)
{
	//TODO : should the SlotValid be cleared to 0 to reuse this entry??
	MLME_initState(psBSS(i));
	OS_MEMORY_CLEAR( psBSS(i)->abBssID, MAC_ADDR_LENGTH );
	OS_MEMORY_CLEAR( &(psBSS(i)->CapabilityInformation), sizeof(struct Capability_Information_Element) );
	OS_MEMORY_CLEAR( &(psBSS(i)->SupportedRateSet), sizeof(struct Supported_Rates_Element) );
	OS_MEMORY_CLEAR( &(psBSS(i)->ERP_Information_Set), sizeof(struct ERP_Information_Element) );
	OS_MEMORY_CLEAR( &(psBSS(i)->ExtendedSupportedRateSet), sizeof(struct Extended_Supported_Rates_Element) );
	psBSS(i)->dwBasicRateBitmap = 0;
	psBSS(i)->dwOperationalRateBitmap = 0;
	//psBSS(i)->RSN_Capability = 0;

	psBSS(i)->ScanTimeStamp = 0;
	psBSS(i)->BssTimeStamp = 0;
	//psBSS(i)->band = 0;
}
//============================================================================
// wBSSfindSSID --
//
// Description:
//   Find the BSSDescriptor entry based on the input SSID
//
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//   psSsid     -   The SSID that will be searched in the BSSDescripotr set
//
// Return:
//   0      - not found
//   other  - the BSSDescriptor entry index of the found STA
//============================================================================
USHORT wBSSfindSSID(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid)
{
	USHORT i;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if ((boMLME_FoundSTAinfo(psBSS(i))) &&
			 (psSsid->Length == psBSS(i)->SSID.Length) &&
			 OS_MEMORY_COMPARE( psSsid->SSID, psBSS(i)->SSID.SSID, psSsid->Length) )
		{
			return i;
		}
	}
	return (USHORT)(0);
}

//============================================================================
// wBSSfindBssID --
//
// Description:
//   Find the BSSDescriptor entry based on the input BSSID
//
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//   psSsid     -   The BSSID that will be searched in the BSSDescripotr set
//
// Return:
//   0      - not found
//   other  - the BSSDescriptor entry index of the found STA
//============================================================================
USHORT wBSSfindBssID(PWB32_ADAPTER Adapter, UCHAR *pbBssid)
{
	USHORT i;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if( boMLME_FoundSTAinfo( psBSS(i) ) &&
			boCmpMacAddr( pbBssid, psBSS(i)->abBssID ) )
		{
			return i;
		}
	}
	return (USHORT)(0);
}

USHORT wBSSfindDedicateCandidate(PWB32_ADAPTER Adapter, struct SSID_Element *psSsid, UCHAR *pbBssid)
{
	USHORT i;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if( boMLME_FoundSTAinfo( psBSS(i) ) &&
			boCmpMacAddr( pbBssid, psBSS(i)->abBssID ) )
		{
			 if ( (psSsid->Length == psBSS(i)->SSID.Length) &&
			 		OS_MEMORY_COMPARE( psSsid->SSID, psBSS(i)->SSID.SSID, psSsid->Length) )
				return i;
		}
	}
	return (USHORT)(0);
}

//============================================================================
// wBSSfindMACaddr --
//
// Description:
//   Find the BSSDescriptor entry based on the input MAC address
//
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//   psSsid     -   The MAC address that will be searched in the BSSDescripotr set
//
// Return:
//   0      - not found
//   other  - the BSSDescriptor entry index of the found STA
//============================================================================
USHORT wBSSfindMACaddr(PWB32_ADAPTER Adapter, UCHAR *pbMacAddr)
{
	USHORT i;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if( boMLME_FoundSTAinfo( psBSS(i) ) &&
			boCmpMacAddr( pbMacAddr, psBSS(i)->abPeerAddress ) )
		{
			return i;
		}
	}
	return (USHORT)(0);
}

USHORT wBSSsearchMACaddr(PWB32_ADAPTER Adapter, UCHAR *pbMacAddr, UCHAR band)
{
	USHORT i;
	USHORT ret = 0;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if (psBSS(i)->SlotValid == 1)
		{	
			if( boCmpMacAddr( pbMacAddr, psBSS(i)->abPeerAddress ) &&
				(band == psBSS(i)->band) )
			{
				ret = i;
		}
	}
	}
	return ret;
}

//============================================================================
// wBSSaddScanData --
//
// Description:
//   The BSSDescriptor entry of the received beacon does not exist, fill the
//   received beacon to the new BSSDescriptor entry.
//
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//   wBssIdx    -   BSSDescriptor entry index that will fill the received beacon
//   psRcvData  -   The received beacon frame
//
// Return:
//   0      - FAIL
//   1      - SUCCESS
//============================================================================
USHORT wBSSaddScanData(PWB32_ADAPTER Adapter, USHORT wBssIdx, psRXDATA psRcvData)
{
	//int index,ElementLength;
	USHORT	index;
	UCHAR*	psRcvFrame;

	psRcvFrame = psRcvData->pbFramePtr;
	OS_MEMORY_COPY( psBSS(wBssIdx)->abPeerAddress, ((struct Management_Frame *)psRcvFrame)->SA,
					MAC_ADDR_LENGTH);
	OS_MEMORY_COPY( psBSS(wBssIdx)->abBssID, ((struct Management_Frame *)psRcvFrame)->BSSID,
					MAC_ADDR_LENGTH);

	index = sizeof(struct Management_Frame);
	//For NDIS_WLAN_BSSID_EX of Windows XP
	//psBSS(wBssIdx)->ies_len = psRcvData->FrameLength - index;
	//memcpy(psBSS(wBssIdx)->ies, psRcvFrame+index, psBSS(wBssIdx)->ies_len);

	//----- Fixed fields -------------------------------------------
	OS_MEMORY_COPY( psBSS(wBssIdx)->Timestamp, psRcvFrame+index, 8 );
	index += 8;

	// Copy Beacon-Period, 2 bytes
	OS_MEMORY_COPY( &(psBSS(wBssIdx)->Beacon_Period), psRcvFrame+index, 2 );
	//20060926 add by anson's endian
	psBSS(wBssIdx)->Beacon_Period = cpu_to_le16(psBSS(wBssIdx)->Beacon_Period);
	index += 2;

	// Copy Capability, 2 bytes
	OS_MEMORY_COPY( &(psBSS(wBssIdx)->CapabilityInformation), psRcvFrame+index,
					sizeof(struct Capability_Information_Element) );
	*(USHORT *)(&psBSS(wBssIdx)->CapabilityInformation) = cpu_to_le16( *(USHORT *)(&psBSS(wBssIdx)->CapabilityInformation) );
	index += sizeof(struct Capability_Information_Element);

	//----- Information Elements -----------------------------------
	//key cipher suites,RsnIe_Type and Rsnie_lens may be updated every beacon,
	//so clear those values to zero   
	psBSS(wBssIdx)->RsnIe_len = 0;
    psBSS(wBssIdx)->Rsn_Num= 0;
    psBSS(wBssIdx)->pairwise_key_cipher_suite_selected=0;
    #ifdef _WPA2_
    psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suite_selected=0;
    #endif
	psBSS(wBssIdx)->DS_Parameter_Set.Length = 0;

	// 20061108 for verify WPS_IE
	psBSS(wBssIdx)->WPS_IE_length_tmp = 0;

	while (index < psRcvData->FrameLength)
	{
		index = GetElement(Adapter, wBssIdx, psRcvFrame, index );
	}

	psBSS(wBssIdx)->WPS_IE_length = psBSS(wBssIdx)->WPS_IE_length_tmp; // 20061108 add

	//----- Analysis -----------------------------------------------
	//Some APs may not contain DS_PARAMETER_SET element
	if (psBSS(wBssIdx)->DS_Parameter_Set.Length == 0)
	{
		psBSS(wBssIdx)->DS_Parameter_Set.Current_Channel = psLOCAL->CurrentChan.ChanNo;
		//psBSS(wBssIdx)->band = psLOCAL->band; //It has been assigned at Mds_MpduProcess()
	}

	//Chenck the band and channel conflict if H/W doesn't indicate the band data.
	//TODO : How about frequency 5040(channel 8), 5060(channel 12) ??
	if ((psBSS(wBssIdx)->DS_Parameter_Set.Current_Channel > 14) &&
		(psBSS(wBssIdx)->band <= BAND_TYPE_OFDM_24))
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("Band & Channel conflict!!\n"));
		#endif
		return 0;
	}

	if (psBSS(wBssIdx)->CapabilityInformation.Capability.IBSS == 0 &&
		psBSS(wBssIdx)->CapabilityInformation.Capability.ESS == 1)
	{
		psBSS(wBssIdx)->bBssType = ESS_NET;
	}
	else if (psBSS(wBssIdx)->CapabilityInformation.Capability.IBSS == 1 &&
			psBSS(wBssIdx)->CapabilityInformation.Capability.ESS == 0)
	{
		psBSS(wBssIdx)->bBssType = IBSS_NET;
	}
	else
	{
		return 0;
	}
//	if (psBSS(wBssIdx)->ScanTimeStamp != psSCAN->ScanTimeStamp)
		psBSS(wBssIdx)->ScanTimeStamp = psSCAN->ScanTimeStamp;
//	if (psBSS(wBssIdx)->BssTimeStamp != psSCAN->BssTimeStamp)
		psBSS(wBssIdx)->BssTimeStamp = psSCAN->BssTimeStamp;
	return 1;
}

static UCHAR ZeroPattern[32]= {0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
						 0,0,0,0,0, 0,0,0,0,0, 0,0};
 
USHORT GetElement( PWB32_ADAPTER Adapter, USHORT wBssIdx, UCHAR * ElementAddr, USHORT Idx )
{
	UCHAR	ElementID = *(ElementAddr+Idx);
	UCHAR	ElementLen = *(ElementAddr+Idx+1);
	UCHAR*	pbElementData = ElementAddr + Idx;
    UCHAR* RsnNum=&psBSS(wBssIdx)->Rsn_Num;
	ULONG OUI_tmp;
	USHORT	Version_tmp, Pairewise_count, Auth_count;

	switch (ElementID)
	{
		case ELEMENT_ID_SSID:
			{
				struct SSID_Element *pSsidTmp;

				pSsidTmp = (struct SSID_Element *)pbElementData;
				if ((pSsidTmp->Length == 0) ||
					OS_MEMORY_COMPARE( pSsidTmp->SSID, ZeroPattern, pSsidTmp->Length ) )
				{
					#ifdef _PE_STATE_DUMP_
					WBDEBUG(("It may be a hidden SSID. Don't update it!\n"));
					#endif
				}
				else
					OS_MEMORY_COPY( &(psBSS(wBssIdx)->SSID), pbElementData, ElementLen+2 );
			}
			break;
		case ELEMENT_ID_SUPPORTED_RATES:
			//Buffalo g54 AP put all rates into the SupportedRateSet(don't have
			// ExtendedSupportedRateSet
			//NOTE:
			//If the length of SupportedRateSet is larger then 8, we suppose the peer
			//STA puts all the rates into SupportedRateSet and doesn't have
			//ExtendedSupportedRateSet
			if (ElementLen>8)
			{
				OS_MEMORY_COPY( &(psBSS(wBssIdx)->SupportedRateSet), pbElementData, 8+2 );
				psBSS(wBssIdx)->SupportedRateSet.Length = 8;
				//The others will be stored into ExtendedSupportedRateSet
				psBSS(wBssIdx)->ExtendedSupportedRateSet.Element_ID = ELEMENT_ID_EXTENDED_SUPPORTED_RATES;
				OS_MEMORY_COPY( psBSS(wBssIdx)->ExtendedSupportedRateSet.ExtendedSupportedRates,
								pbElementData+10, ElementLen-8 );
				psBSS(wBssIdx)->ExtendedSupportedRateSet.Length = ElementLen-8;
			}
			else
				OS_MEMORY_COPY( &(psBSS(wBssIdx)->SupportedRateSet), pbElementData, ElementLen+2 );
			break;
		case ELEMENT_ID_FH_PARAMETER_SET:
			break;
		case ELEMENT_ID_DS_PARAMETER_SET:
			if ((wBssIdx == psLOCAL->wConnectedSTAindex) &&
				(((struct DS_Parameter_Set_Element*)pbElementData)->Current_Channel
				 != psBSS(wBssIdx)->DS_Parameter_Set.Current_Channel))
			{
				//TODO: If the band is different, then ???
				#ifdef _PE_STATE_DUMP_
				WBDEBUG(("!!!The channel of AP has been changed.\n"));
				#endif
				psLOCAL->boReceiveUncorrectInfo = TRUE;
			}
			else
			{
				OS_MEMORY_COPY( &(psBSS(wBssIdx)->DS_Parameter_Set), pbElementData, ElementLen+2 );
				//psBSS(wBssIdx)->band = psLOCAL->band;//It has been assigned at Mds_MpduProcess()
			}
			break;
		case ELEMENT_ID_CF_PARAMETER_SET:
			OS_MEMORY_COPY( &(psBSS(wBssIdx)->CF_Parameter_Set), pbElementData, ElementLen+2 );
			break;
		case ELEMENT_ID_TIM:
			OS_MEMORY_COPY( &(psBSS(wBssIdx)->TIM_Element_Set), pbElementData, ElementLen+2 );
			break;
		case ELEMENT_ID_IBSS_PARAMETER_SET:
			OS_MEMORY_COPY( &(psBSS(wBssIdx)->IBSS_Parameter_Set), pbElementData, ElementLen+2 );
			//20060926 add by anson's endian
			*(USHORT *)psBSS(wBssIdx)->IBSS_Parameter_Set.ATIM_Window =
						cpu_to_le16(*(USHORT *)psBSS(wBssIdx)->IBSS_Parameter_Set.ATIM_Window);
			break;
		case ELEMENT_ID_ERP_INFORMATION:
			OS_MEMORY_COPY( &(psBSS(wBssIdx)->ERP_Information_Set), pbElementData, ElementLen+2 );
			if ((wBssIdx == psLOCAL->wConnectedSTAindex) &&
				(psBSS(psLOCAL->wConnectedSTAindex)->bBssType == ESS_NET))
			{	//follow the setting of AP
				psLOCAL->boNonERPpresent = psBSS(wBssIdx)->ERP_Information_Set.NonERP_Present;
				psLOCAL->boProtectMechanism = psBSS(wBssIdx)->ERP_Information_Set.Use_Protection;
				if (psLOCAL->bPreambleMode == AUTO_MODE)
				{
					if (psBSS(wBssIdx)->ERP_Information_Set.Barker_Preamble_Mode)
						psLOCAL->boShortPreamble = 0;
					else
						psLOCAL->boShortPreamble = 1;
				}
				//The ShortSlotTime in capability may change during the connection?? Yes!
				if (psLOCAL->bSlotTimeMode == AUTO_MODE)
				{
					if (psLOCAL->boShortSlotTime != psBSS(wBssIdx)->CapabilityInformation.Capability.Short_Slot_Time)
					{
						psLOCAL->boShortSlotTime = psBSS(wBssIdx)->
									CapabilityInformation.Capability.Short_Slot_Time;
						if (psBSS(wBssIdx)->CapabilityInformation.Capability.Short_Slot_Time)
							hal_set_slot_time(&Adapter->sHwData, WLAN_SLOT_TIME_TYPE_SHORT);
						else
							hal_set_slot_time(&Adapter->sHwData, WLAN_SLOT_TIME_TYPE_LONG);
					}
				}
			}
			break;
		case ELEMENT_ID_EXTENDED_SUPPORTED_RATES:
			OS_MEMORY_COPY( &(psBSS(wBssIdx)->ExtendedSupportedRateSet), pbElementData, ElementLen+2 );
			break;
		//--------------------------------------------------------------------------------------------
		// modified by ws at 09/14/04. To parse received frame and save avaliable data to
		// data descriptor.
		//--------------------------------------------------------------------------------------------
		//TODO : [1004]
		case ELEMENT_ID_RSN_WPA:
            //if wpa rsn and wpa2 rsn are included in the same beacon or probe response, both wpa and wpa2 
            //cipher suites will be placed in different place,otherwise the RsnIe_Type will be WPA2 rather than WPA,
            //since WPA2 has higher priority.
			{
				struct RSN_Information_Element* rsnie=(struct RSN_Information_Element *)pbElementData;
				struct RSN_Auth_Sub_Information_Element * auth_cipher;
                USHORT i;
				UCHAR  LenTmp = 0;

				//added a condition for comparing OUI by ws 09/23/04
				if( rsnie->Length < WLAN_MIN_RSN_WPA_LENGTH )
					break;

				// 20061108 Modify for WPS
				OS_MEMORY_COPY( &Version_tmp, &rsnie->Version, sizeof(USHORT) );
				OS_MEMORY_COPY( &OUI_tmp, &rsnie->OuiWPAAdditional, sizeof(ULONG) );
				//20060926 add by anson's endian
				Version_tmp = cpu_to_le16( Version_tmp );
				OUI_tmp = cpu_to_le32( OUI_tmp );

				if( Version_tmp !=1 )
					break;

				// 20061108 WPS OUI support
				if( ElementAddr[0]==0x50 && OUI_tmp==WPA_WPS_OUI ) // Storing all field of WPS information of Probe response(0x50)
				{
					OS_MEMORY_COPY( &psBSS(wBssIdx)->WPS_IE_Data, pbElementData, ElementLen + 2 );
					psBSS(wBssIdx)->WPS_IE_length_tmp = ElementLen;
					break; // End of WSC IE processing
				}

				if( (OUI_tmp != WPA_OUI_BIG) && (OUI_tmp != WPA_OUI_LITTLE) )
					break;

				LenTmp = 6;//OuiWPAAdditional && version
				//802.11i/D4.0 :
				//If any optional field is absent, none of the subsequent
				//fields shall be included.
				do
				{
					if (rsnie->Length >= 10)// checking group cipher suite are included in rsn
					{
						OS_MEMORY_COPY( &(psBSS(wBssIdx)->group_cipher), &rsnie->GroupKeySuite, sizeof(OUI_WPA) );
						LenTmp += 4;
					}
					else
						break;
					if(rsnie->Length >= 12)	//PairwiseKey suite count field exists
					{
						OS_MEMORY_COPY( &Pairewise_count, &rsnie->PairwiseKeySuiteCount, sizeof(USHORT) );
						//20060926 add by anson's endian
						Pairewise_count = cpu_to_le16( Pairewise_count );
						if( (Pairewise_count > WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT) ||
							(rsnie->Length < (12 + Pairewise_count * 4)) )
						{
							break;
						}
						else
						{
							psBSS(wBssIdx)->pairwise_key_cipher_suite_count = Pairewise_count;
							OS_MEMORY_COPY( &psBSS(wBssIdx)->pairwise_key_cipher_suites[0],
											rsnie->PairwiseKeySuite, Pairewise_count * 4);

							LenTmp += (2+(Pairewise_count<<2));
							//for multi pairwise key cipher suites, priority of CCMP > TKIP priority
                            for( i=0; i<Pairewise_count; i++ )
							{
								if( psBSS(wBssIdx)->pairwise_key_cipher_suite_selected==0 ||
									psBSS(wBssIdx)->pairwise_key_cipher_suite_selected < rsnie->PairwiseKeySuite[i].SuitSelector.Type )
									psBSS(wBssIdx)->pairwise_key_cipher_suite_selected=rsnie->PairwiseKeySuite[i].SuitSelector.Type;
							}
						}
					}
					else
						break;
					if(rsnie->Length >= (LenTmp+2))
					{
						//point to a structure of RSN_authentucation information, included ID and length fields
						auth_cipher = (struct RSN_Auth_Sub_Information_Element *)(pbElementData+(LenTmp+2));
						OS_MEMORY_COPY( &Auth_count, &auth_cipher->AuthKeyMngtSuiteCount, sizeof(USHORT) );
						//20060926 add by anson's endian
						Auth_count = cpu_to_le16( Auth_count );
						if( (Auth_count > WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT) ||
							(rsnie->Length < (LenTmp + 2 +(Auth_count<<2))) )
						{
							break;
						}
						else
						{
							psBSS(wBssIdx)->auth_key_mgt_suite_count = Auth_count;
							OS_MEMORY_COPY( &psBSS(wBssIdx)->auth_key_mgt_suites, auth_cipher->AuthKeyMngtSuite,
											Auth_count * 4);
							LenTmp += (2+(Auth_count<<2));
						}
					}
					else
						break;
					if (rsnie->Length >= (LenTmp+2))	//RSN capability exists
					{
						//address of RSN capability
						OS_MEMORY_COPY( &(psBSS(wBssIdx)->rsn_capabilities), pbElementData+(LenTmp+2), 2 );
						//20060926 add by anson's endian
						*(USHORT *)&(psBSS(wBssIdx)->rsn_capabilities) =
										cpu_to_le16( *(USHORT *)&(psBSS(wBssIdx)->rsn_capabilities) );
						LenTmp += 2;
					}

				    psBSS(wBssIdx)->RsnIe_Type[*RsnNum] = ElementID;
				    psBSS(wBssIdx)->RsnIe_len += LenTmp;
                    (*RsnNum)++;
                    
				}while (FALSE);
			}
			break;
		#ifdef _WPA2_
		case ELEMENT_ID_RSN_WPA2:
			{
                struct WPA2_RSN_Information_Element* wpa2_rsnie = (struct WPA2_RSN_Information_Element *)pbElementData;
				struct WPA2_RSN_Auth_Sub_Information_Element * wpa2_auth_cipher;
				UCHAR	LenTmp = 0;
                USHORT i, Auth_count;

				//added a condition for checking OUI
				if( wpa2_rsnie->Length < WLAN_MIN_RSN_WPA2_LENGTH )
					break;
				else
				{
					OS_MEMORY_COPY( &Version_tmp, &wpa2_rsnie->Version, sizeof(USHORT) );
					//20060926 add by anson's endian
					Version_tmp = cpu_to_le16( Version_tmp );
					if( Version_tmp != 1 )
						break;
				}
				LenTmp = 2;//version

				do
				{   //measure rsn included the group cipher suite into
					if (wpa2_rsnie->Length >= 6)
					{
						OS_MEMORY_COPY( &(psBSS(wBssIdx)->wpa2_group_cipher), &wpa2_rsnie->GroupKeySuite, sizeof(OUI_WPA2) );
						LenTmp += 4;
					}
					else
						break;

					if( wpa2_rsnie->Length >= 8 ) //PairwiseKey suite count field exists
					{
						OS_MEMORY_COPY( &Pairewise_count, &wpa2_rsnie->PairwiseKeySuiteCount, sizeof(USHORT) );
						//20060926 add by anson's endian
						Pairewise_count = cpu_to_le16( Pairewise_count );
						if( (Pairewise_count > WLAN_MAX_PAIRWISE_CIPHER_SUITE_COUNT) ||
							(wpa2_rsnie->Length < (8 + Pairewise_count * 4)) )
						{
							break;
						}
						else
						{
							psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suite_count = Pairewise_count;
							OS_MEMORY_COPY( &psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suites[0],
											wpa2_rsnie->PairwiseKeySuite, Pairewise_count * 4 );

							LenTmp += (2 + (Pairewise_count<<2));
							//for multi pairwise key cipher suite, CCMP>TKIP
                            for( i=0; i<Pairewise_count; i++ )
							{
								if( psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suite_selected==0 ||
									psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suite_selected < wpa2_rsnie->PairwiseKeySuite[i].SuitSelector.Type )
									psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suite_selected=wpa2_rsnie->PairwiseKeySuite[i].SuitSelector.Type;
							}
						}
					}
					else
						break;

					if( wpa2_rsnie->Length >= (LenTmp+2) ) //authentication suite count field exists
					{
						//address of authentication suite
						//include ID and length fields
						wpa2_auth_cipher = (struct WPA2_RSN_Auth_Sub_Information_Element *)(pbElementData + (LenTmp+2) );
						OS_MEMORY_COPY( &Auth_count, &wpa2_auth_cipher->AuthKeyMngtSuiteCount, sizeof(USHORT) );
						//20060926 add by anson's endian
						Auth_count = cpu_to_le16( Auth_count );
						if( (Auth_count > WLAN_MAX_AUTH_KEY_MGT_SUITE_LIST_COUNT) ||
							(wpa2_rsnie->Length < (LenTmp + 2 +(Auth_count<<2))) )
						{
							break;
						}
						else
						{
							psBSS(wBssIdx)->wpa2_auth_key_mgt_suite_count = Auth_count;
							OS_MEMORY_COPY( &psBSS(wBssIdx)->wpa2_auth_key_mgt_suites,
											wpa2_auth_cipher->AuthKeyMngtSuite, Auth_count * 4 );
							
							LenTmp += (2+(Auth_count<<2));
						}
					}
					else
						break;

					if (wpa2_rsnie->Length >= (LenTmp+2))	//RSN capability exists
					{
						//address of RSN capability
						OS_MEMORY_COPY( &(psBSS(wBssIdx)->wpa2_rsn_capabilities), pbElementData+(LenTmp+2), sizeof(struct RSN_Capability_Element) );
						//20060926 add by anson's endian
						*(USHORT *)&(psBSS(wBssIdx)->wpa2_rsn_capabilities) =
									cpu_to_le16( *(USHORT *)&(psBSS(wBssIdx)->wpa2_rsn_capabilities) );
                        //to check this AP supports pre authenctication or not 
                        if(psBSS(wBssIdx)->rsn_capabilities.RSN_Capability.Pre_Auth)
                            psBSS(wBssIdx)->pre_auth=TRUE;
                        else
                            psBSS(wBssIdx)->pre_auth=FALSE;
                            
						LenTmp += 2;
					}

				    psBSS(wBssIdx)->RsnIe_Type[*RsnNum]= ElementID;
                    psBSS(wBssIdx)->RsnIe_len += LenTmp;
                    (*RsnNum)++;
				}while (FALSE);
				
			}
            #endif
		default:
			break;
	}

	Idx +=(ElementLen+2);
	return Idx;
}

//==========================================================================
// modified by WS 09/15/04 
// for solving WWU showed up error message "LIST index out of bounds (5)"
// and "Access violation at address 00407494 in module" when receive csico AP 
// beacon.The solution is to filter out useless data and reassemble 
// information element send to NDIS.
//
//===========================================================================
void Assemble_IE(PWB32_ADAPTER Adapter, USHORT wBssIdx)
{
	WB_BSSDESCRIPTION *Desc=psBSS(wBssIdx);
	struct RSN_Information_Element *rsn_ie;
	struct RSN_Auth_Sub_Information_Element *auth_sub_ie;

    #ifdef _WPA2_
    struct WPA2_RSN_Information_Element *WPA2_rsn_ie;
    struct WPA2_RSN_Auth_Sub_Information_Element *WPA2_auth_sub_ie;
    #endif //end def _WPA2_

    UCHAR	LenLeft=psBSS(wBssIdx)->RsnIe_len;
    UCHAR  RsnNo=0;
	UCHAR ies_len=0;
	UCHAR *IEs=psBSS(wBssIdx)->ies;
	ULONG	uValue;
	USHORT	Pairwise_count, Auth_count;
	USHORT	Version_tmp;

    Desc->ies_len=0;

	vRateToBitmap(Adapter, wBssIdx);
	psBSS(wBssIdx)->boERP = boIsERPsta(Adapter, wBssIdx);

	// fix field for ndis
	OS_MEMORY_COPY( IEs ,&Desc->Timestamp, 8 );
	ies_len+=8;
	IEs+=8;

	OS_MEMORY_COPY( IEs, &Desc->Beacon_Period, 2 );
	//20060926 add by anson's endian
	*(USHORT *)IEs = cpu_to_le16( *(USHORT *)IEs );
	ies_len+=2;
	IEs += 2;

	OS_MEMORY_COPY( IEs, &Desc->CapabilityInformation, sizeof(struct Capability_Information_Element) );
	//20060926 add by anson's endian
	*(USHORT *)IEs = cpu_to_le16( *(USHORT *)IEs );
	ies_len+=sizeof(struct Capability_Information_Element);
	IEs += sizeof(struct Capability_Information_Element);

    if(Desc->SSID.Length!=0)
    {
		OS_MEMORY_COPY( IEs, &Desc->SSID, Desc->SSID.Length+2 );
		ies_len+=Desc->SSID.Length+2;
		IEs += (Desc->SSID.Length+2);
    }
    
    if(Desc->SupportedRateSet.Length!=0)
    {
		OS_MEMORY_COPY( IEs, &Desc->SupportedRateSet, Desc->SupportedRateSet.Length+2 );
		ies_len+= Desc->SupportedRateSet.Length+2;
		IEs += (Desc->SupportedRateSet.Length+2);
    }
    
    if(Desc->DS_Parameter_Set.Length!=0)
	{
		OS_MEMORY_COPY( IEs, &Desc->DS_Parameter_Set, Desc->DS_Parameter_Set.Length+2 );
		ies_len+=Desc->DS_Parameter_Set.Length+2;
		IEs += (Desc->DS_Parameter_Set.Length+2);
	}
    
    if(Desc->TIM_Element_Set.Length!=0)
	{
		OS_MEMORY_COPY( IEs, &Desc->TIM_Element_Set, Desc->TIM_Element_Set.Length+2 );
        ies_len+=Desc->TIM_Element_Set.Length+2;
	    IEs += (Desc->TIM_Element_Set.Length + 2);
	}

    if(Desc->ERP_Information_Set.Length!=0)
	{
		OS_MEMORY_COPY( IEs, &Desc->ERP_Information_Set, Desc->ERP_Information_Set.Length+2 );
	    ies_len+=Desc->ERP_Information_Set.Length+2;
	    IEs += (Desc->ERP_Information_Set.Length + 2);
	}

    if(Desc->ExtendedSupportedRateSet.Length!=0)
	{
		OS_MEMORY_COPY( IEs, &Desc->ExtendedSupportedRateSet, Desc->ExtendedSupportedRateSet.Length+2 );
	    ies_len+=Desc->ExtendedSupportedRateSet.Length+2;
	    IEs += (Desc->ExtendedSupportedRateSet.Length+2);
	}

	//================================================================================
	//RSN_IE
	//================================================================================
    while (LenLeft)
	{
    	if (psBSS(wBssIdx)->RsnIe_Type[RsnNo] == ELEMENT_ID_RSN_WPA)
		{
			//UCHAR	LenLeft;
			rsn_ie = (struct RSN_Information_Element *)IEs;
			rsn_ie->Element_ID = psBSS(wBssIdx)->RsnIe_Type[RsnNo];
			rsn_ie->Length = 0;

			//20060926 add by anson's endian
			//uValue = (ULONG)(OUI_WPA | (OUI_WPA_ADDITIONAL<<24));
			uValue = cpu_to_le32((ULONG)(OUI_WPA | (OUI_WPA_ADDITIONAL<<24)));
			OS_MEMORY_COPY( &rsn_ie->OuiWPAAdditional, &uValue, sizeof(ULONG) );
			//20060926 add by anson's endian
			//Version_tmp = VERSION_WPA;
			Version_tmp = cpu_to_le16( VERSION_WPA );
			OS_MEMORY_COPY( &rsn_ie->Version, &Version_tmp, sizeof(USHORT) );
			LenLeft =LenLeft -6;
			rsn_ie->Length +=6;
                
			do
			{
				if (LenLeft != 0)
				{
					OS_MEMORY_COPY( &rsn_ie->GroupKeySuite, &Desc->group_cipher, sizeof(ULONG) );
					LenLeft -= 4;
                    rsn_ie->Length +=4;
				}
				else
					break;
				if (LenLeft != 0)
				{
					OS_MEMORY_COPY( &Pairwise_count, &Desc->pairwise_key_cipher_suite_count, sizeof(USHORT) );
					OS_MEMORY_COPY( &rsn_ie->PairwiseKeySuiteCount, &Pairwise_count, sizeof(USHORT) );
					//20060926 add by anson's endian
					*(USHORT *)&rsn_ie->PairwiseKeySuiteCount = 
								cpu_to_le16( *(USHORT *)&rsn_ie->PairwiseKeySuiteCount );
					OS_MEMORY_COPY( &rsn_ie->PairwiseKeySuite, &Desc->pairwise_key_cipher_suites, Pairwise_count<<2 );
					LenLeft -= (2 + (Pairwise_count<<2));
                    rsn_ie->Length +=(2 + (Pairwise_count<<2));
				}
				else
					break;

				OS_MEMORY_COPY( &Auth_count, &Desc->auth_key_mgt_suite_count, sizeof(USHORT) );

				if (LenLeft != 0)
				{
					auth_sub_ie = (struct RSN_Auth_Sub_Information_Element *)((UCHAR *)&rsn_ie->PairwiseKeySuite +
										 (Desc->pairwise_key_cipher_suite_count<<2));

					OS_MEMORY_COPY( &auth_sub_ie->AuthKeyMngtSuiteCount, &Auth_count, sizeof(USHORT) );
					//20060926 add by anson's endian
					*(USHORT *)&auth_sub_ie->AuthKeyMngtSuiteCount = 
							cpu_to_le16(*(USHORT *)&auth_sub_ie->AuthKeyMngtSuiteCount);
					OS_MEMORY_COPY( &auth_sub_ie->AuthKeyMngtSuite, &Desc->auth_key_mgt_suites, Auth_count<<2 );

					LenLeft -= (2 + (Auth_count<<2));
                    rsn_ie->Length +=(2 + (Auth_count<<2));
				}
				else
					break;

				if (LenLeft != 0)	//RSN capability
				{
					//20060926 add by anson's endian
					USHORT TValue = *(USHORT *)&Desc->rsn_capabilities;
					TValue = cpu_to_le16( TValue );
					
					OS_MEMORY_COPY( ((UCHAR *)&auth_sub_ie->AuthKeyMngtSuite) + (Auth_count<<2),
									//&(Desc->rsn_capabilities), sizeof(struct RSN_Capability_Element) ); //20060926 change anson's endian
									&TValue, sizeof(struct RSN_Capability_Element) );
					
					LenLeft -= 2;
                    rsn_ie->Length += 2;
				}
				if (LenLeft != 0)
				{
					#ifdef _PE_STATE_DUMP_
					WBDEBUG((" !!!If this is not the last RsnIE that is Panic !!! WPA RSN IE is wrong.\n"));
					#endif
					break;
				}
			}while (FALSE);

            IEs += rsn_ie->Length+2;
            ies_len += rsn_ie->Length+2;
		}
        #ifdef _WPA2_
		else//WPA2 RSN_IE
		{
            //UCHAR	LenLeft;
			WPA2_rsn_ie = (struct WPA2_RSN_Information_Element *)IEs;
    		WPA2_rsn_ie->Element_ID = psBSS(wBssIdx)->RsnIe_Type[RsnNo];
    		WPA2_rsn_ie->Length = 0;
			//20060926 add by anson's endian
			//Version_tmp = VERSION_WPA2;
			Version_tmp = cpu_to_le16( VERSION_WPA2 );
			OS_MEMORY_COPY( &WPA2_rsn_ie->Version, &Version_tmp, sizeof(USHORT) );
    		LenLeft -=2;
            WPA2_rsn_ie->Length +=2;
			do
			{
				if (LenLeft != 0)
				{
					OS_MEMORY_COPY( &WPA2_rsn_ie->GroupKeySuite, &Desc->wpa2_group_cipher, sizeof(SUITE_SELECTOR) );
					LenLeft -= 4;
                    WPA2_rsn_ie->Length +=4;
				}
				else
					break;

				if (LenLeft != 0)
				{
					OS_MEMORY_COPY( &Pairwise_count, &Desc->wpa2_pairwise_key_cipher_suite_count, sizeof(USHORT) );
					OS_MEMORY_COPY( &WPA2_rsn_ie->PairwiseKeySuiteCount, &Pairwise_count, sizeof(USHORT) );
					//20060926 add by anson's endian
					*(USHORT *)&WPA2_rsn_ie->PairwiseKeySuiteCount = 
								cpu_to_le16( *(USHORT *)&WPA2_rsn_ie->PairwiseKeySuiteCount );
					//wpa2_pairwise_key_cipher_suite_count*4
					OS_MEMORY_COPY( &WPA2_rsn_ie->PairwiseKeySuite, &Desc->wpa2_pairwise_key_cipher_suites, Pairwise_count<<2);
					
					LenLeft -= (2 + (Pairwise_count<<2));
                    WPA2_rsn_ie->Length +=(2 + (Pairwise_count<<2));
				}
				else
					break;
				if (LenLeft != 0)
				{
					WPA2_auth_sub_ie = (struct WPA2_RSN_Auth_Sub_Information_Element *)((UCHAR *)&WPA2_rsn_ie->PairwiseKeySuite +
										 (Desc->wpa2_pairwise_key_cipher_suite_count<<2));

					OS_MEMORY_COPY( &Auth_count, &Desc->wpa2_auth_key_mgt_suite_count, sizeof(USHORT) );
					OS_MEMORY_COPY( &WPA2_auth_sub_ie->AuthKeyMngtSuiteCount, &Auth_count, sizeof(USHORT) );
					//20060926 add by anson's endian
					*(USHORT *)&WPA2_auth_sub_ie->AuthKeyMngtSuiteCount = 
								cpu_to_le16( *(USHORT *)&WPA2_auth_sub_ie->AuthKeyMngtSuiteCount );
					OS_MEMORY_COPY( &WPA2_auth_sub_ie->AuthKeyMngtSuite, &Desc->wpa2_auth_key_mgt_suites, Auth_count<<2 );

					LenLeft -= (2 + (Auth_count<<2));
                    WPA2_rsn_ie->Length +=(2 + (Auth_count<<2));
				}
				else
					break;
				if (LenLeft != 0)	//RSN capability
				{
					//20060926 add by anson's endian
					USHORT TValue = *(USHORT *)&Desc->wpa2_rsn_capabilities;
					TValue = cpu_to_le16( TValue );
					OS_MEMORY_COPY( ((UCHAR *)&WPA2_auth_sub_ie->AuthKeyMngtSuite + (Auth_count<<2) ),
									//&(Desc->wpa2_rsn_capabilities), sizeof(struct RSN_Capability_Element) ); //20060926 modify by anson's endian
									&TValue, sizeof(struct RSN_Capability_Element) );
					LenLeft -= 2;
                    WPA2_rsn_ie->Length +=2;
				}
                else
                    break;
				if (LenLeft != 0)
				{
					#ifdef _PE_STATE_DUMP_
					WBDEBUG((" If this is not the last RsnIE that is Panic !!! Panic !!! WPA2 RSN IE is wrong.\n"));
					#endif
					break;
				}
			}while (FALSE);
        
            IEs += WPA2_rsn_ie->Length+2;
            ies_len += WPA2_rsn_ie->Length+2;
		}
        #endif //end WPA2

		RsnNo++;
	}

	Desc->ies_len=(ULONG)(ies_len);

	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("<<dump IE: idx =%d, IE len =%d >>\n", wBssIdx, ies_len));
	DataDmp( Desc->ies, Desc->ies_len, 0);
	#endif

}
//============================================================================
// wBSSUpdateScanData --
//
// Description:
//   The BSSDescriptor entry of the received beacon has exist, just update
//   the necessary information.(Only Update Capability and ERP elements)
//
// Arguments:
//   Adapter    -   The handle of an adapter bock.
//   wBssIdx    -   BSSDescriptor entry index of received beacon
//   psRcvData  -   The received beacon frame
//
// Return:
//   0      - FAIL
//   1      - SUCCESS
//============================================================================
USHORT wBSSUpdateScanData(PWB32_ADAPTER Adapter, USHORT wBssIdx, psRXDATA psRcvData)
{
	USHORT index;
	UCHAR*	psRcvFrame;

	#ifdef _PE_STATE_DUMP_
	//WBDEBUG(("UpdateScanData\n"));
	#endif

	psRcvFrame = psRcvData->pbFramePtr;

	OS_MEMORY_COPY( psBSS(wBssIdx)->abBssID, ((struct Management_Frame *)psRcvFrame)->BSSID, MAC_ADDR_LENGTH);
	//WBDEBUG(("Rcv beacon/probe resp. BSSID=\n"));
	//DataDmp(psBSS(wBssIdx)->abBssID, 6, 0);

	index = sizeof(struct Management_Frame);
	//For NDIS_WLAN_BSSID_EX of Windows XP
	//psBSS(wBssIdx)->ies_len = psRcvData->FrameLength - index;
	//memcpy(psBSS(wBssIdx)->ies, psRcvFrame+index, psBSS(wBssIdx)->ies_len);

	//----- Fixed fields -------------------------------------------
	OS_MEMORY_COPY( psBSS(wBssIdx)->Timestamp, psRcvFrame+index, 8 );
	index += 8;

	// Copy Beacon-Period, 2 bytes
	//Suppose AP will disassociate if the Beacon-Period is changed.
	OS_MEMORY_COPY( &(psBSS(wBssIdx)->Beacon_Period), psRcvFrame+index, 2 );
	//20060926 add by anson's endian
	psBSS(wBssIdx)->Beacon_Period = cpu_to_le16( psBSS(wBssIdx)->Beacon_Period );
	index += 2;

	// Copy Capability, 2 bytes
	OS_MEMORY_COPY( &(psBSS(wBssIdx)->CapabilityInformation), psRcvFrame+index,
					sizeof(struct Capability_Information_Element));
	//20060926 add by anson's endian
	*(USHORT *)&psBSS(wBssIdx)->CapabilityInformation = 
			cpu_to_le16( *(USHORT *)&psBSS(wBssIdx)->CapabilityInformation );
	index += sizeof(struct Capability_Information_Element);

	//----- Information Elements -----------------------------------
	psBSS(wBssIdx)->RsnIe_len = 0;
    psBSS(wBssIdx)->Rsn_Num= 0;
    psBSS(wBssIdx)->pairwise_key_cipher_suite_selected=0;
    #ifdef _WPA2_
    psBSS(wBssIdx)->wpa2_pairwise_key_cipher_suite_selected=0;
    #endif
	psBSS(wBssIdx)->DS_Parameter_Set.Length = 0;

	// 20061108 for verify WPS_IE
	psBSS(wBssIdx)->WPS_IE_length_tmp = 0; // GetElement will modify this variable

	while (index < psRcvData->FrameLength)
	{
		index = GetElement(Adapter, wBssIdx, psRcvFrame, index );
	}

	psBSS(wBssIdx)->WPS_IE_length = psBSS(wBssIdx)->WPS_IE_length_tmp; // 20061108 add

	//----- Analysis -----------------------------------------------

	//TODO : channel has been changed
	//Some APs may not contain DS_PARAMETER_SET element
	if (psBSS(wBssIdx)->DS_Parameter_Set.Length == 0)
	{
		psBSS(wBssIdx)->DS_Parameter_Set.Current_Channel = psLOCAL->CurrentChan.ChanNo;
		//psBSS(wBssIdx)->band = psLOCAL->band; //It has been assigned at Mds_MpduProcess()
	}

	//The channel of AP had been changed
	if (psLOCAL->boReceiveUncorrectInfo)
	{
		K_MSG sMsg;
		USHORT		wReasonCode;

		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("<<dump IE: idx =%d, IE len =%d >>\n", wBssIdx, psRcvData->FrameLength));
		DataDmp( psRcvFrame, psRcvData->FrameLength, 0);
		#endif

		wReasonCode = REASON_CLASS3_FRAME_FROM_NONASSO_STA;
		sMsg.wMsgType = SMEMSG_DISASSOC_REQ;
		sMsg.pMsgPtr = &wReasonCode;
		SME_Entry(Adapter, &sMsg);
		psLOCAL->boReceiveUncorrectInfo = FALSE;
		return 0;
	}
	//----- Analysis -----------------------------------------------
	if (psBSS(wBssIdx)->CapabilityInformation.Capability.IBSS == 0 &&
		psBSS(wBssIdx)->CapabilityInformation.Capability.ESS == 1)
	{
		//psBSS(wBssIdx)->bBssType = ESS_NET;
		//check for connection status
		if (wBssIdx == psLOCAL->wConnectedSTAindex)
		{
			psLOCAL->bConnectFlag = 1;
			#ifdef _PE_STATE_DUMP_
			//WBDEBUG(("Update ESS scan data, connect flag = 1\n"));
			#endif
		}
	}
	else if (psBSS(wBssIdx)->CapabilityInformation.Capability.IBSS == 1 &&
			psBSS(wBssIdx)->CapabilityInformation.Capability.ESS == 0)
	{
		//psBSS(wBssIdx)->bBssType = IBSS_NET;
		//check BSSID for connection status
		if ((wBssIdx != psLOCAL->wConnectedSTAindex) &&
			( boCmpMacAddr( psBSS(psLOCAL->wConnectedSTAindex)->abBssID, psBSS(wBssIdx)->abBssID ) ) )
		{
			psLOCAL->bConnectFlag = 1;
			#ifdef _PE_STATE_DUMP_
			//WBDEBUG(("Update IBSS scan data, connect flag = 1\n"));
			#endif
		}
	}
	else
	{
		return 0;
	}
//	if (psBSS(wBssIdx)->ScanTimeStamp != psSCAN->ScanTimeStamp)
		psBSS(wBssIdx)->ScanTimeStamp = psSCAN->ScanTimeStamp;
//	if (psBSS(wBssIdx)->BssTimeStamp != psSCAN->BssTimeStamp)
		psBSS(wBssIdx)->BssTimeStamp = psSCAN->BssTimeStamp;
	return 1;
}

//for START IBSS only, copy SME parameter to local description
USHORT wBSScreateIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData)
{
	ULONG	ltime;
	ULONG	tmp1;
	ULONG	BitMap;
	UCHAR	BSSID[MAC_ADDR_LENGTH];
	UCHAR	i, j, BitIndex;

	//fill the start IBSS parameters in sSmePara to the description
	OS_MEMORY_COPY( psDesData->abPeerAddress, psLOCAL->ThisMacAddress, MAC_ADDR_LENGTH );
	psDesData->bBssType = IBSS_NET;
	psDesData->Beacon_Period = psSME->wBeaconPeriod;
	// Generate the BSSID
	// bit 0 = 0, bit 1 = 1, other 46 bits: randomly generated.
    ///NdisGetSystemUpTime(&ltime);
	OS_TIMER_GET_SYS_TIME( &ltime );
	OS_MEMORY_COPY( BSSID + 2, &ltime, sizeof(ULONG) );
    ///NdisGetSystemUpTime(&ltime);
	OS_TIMER_GET_SYS_TIME( &ltime );
	// PD43 20030117 Modified. Zero the 6 msb of the first byte of the BSSID.
    // *(USHORT*)&BSSID[0] = (USHORT) (~(ULONG)ltime & 0x0000fffc) | 0x0002;
    //*(USHORT*)&BSSID[0] = (USHORT) (~(ULONG)ltime & 0x0000ff00) | 0x0002;
    *(USHORT*)&BSSID[0] = cpu_to_le16((USHORT) (~(ULONG)ltime & 0x0000ff00) | 0x0002);  //20061009 anson's endian
	OS_MEMORY_COPY( psDesData->abBssID, BSSID, MAC_ADDR_LENGTH );

	// SSID.IE
	psDesData->SSID.Length = psSME->sDesiredSSID.Length;
	OS_MEMORY_COPY( psDesData->SSID.SSID, psSME->sDesiredSSID.SSID, psSME->sDesiredSSID.Length );
	psDesData->band = psSME->IbssChan.band;
	psDesData->DS_Parameter_Set.Current_Channel = psSME->IbssChan.ChanNo;

	psDesData->wATIM_Window = psSME->wATIM_Window;

	psSME->wCapabilityInfo = CAPABILITY_IBSS_BIT;	//IBSS
	if (psSME->_dot11PrivacyInvoked)
		psSME->wCapabilityInfo |= CAPABILITY_PRIVACY_BIT;   // Privacy
	if (psLOCAL->bMacOperationMode == MODE_802_11_BG_IBSS)
		psSME->wCapabilityInfo |= CAPABILITY_SHORT_PREAMBLE_BIT;
	//In IBSS, short slot bit should always be 0
	psDesData->CapabilityInformation.wValue = psSME->wCapabilityInfo;

	if (psSME->boDUTmode == FALSE)	//use default rates
	{
		switch (psLOCAL->bMacOperationMode)
		{
			case MODE_802_11_A:
				psSME->BasicRateBitmap = LOCAL_11A_BASIC_RATE_BITMAP;
				psSME->OpRateBitmap = LOCAL_11A_OPERATION_RATE_BITMAP;
				break;
			case MODE_802_11_BG_IBSS:
				if (psSME->IbssChan.ChanNo != 14)
				{
					psSME->BasicRateBitmap = LOCAL_11G_BASIC_RATE_BITMAP;
					psSME->OpRateBitmap = LOCAL_11G_OPERATION_RATE_BITMAP;
				}
				else
				{
					//channel 14 can't use OFDM rates
					psSME->BasicRateBitmap = LOCAL_11B_BASIC_RATE_BITMAP;
					psSME->OpRateBitmap = LOCAL_11B_OPERATION_RATE_BITMAP;
				}
				break;
			case MODE_802_11_ABG:
			case MODE_802_11_B:
				psSME->BasicRateBitmap = LOCAL_11B_BASIC_RATE_BITMAP;
				psSME->OpRateBitmap = LOCAL_11B_OPERATION_RATE_BITMAP;
				break;
			case MODE_AUTO:
			default: // 20061017 1.0.46.18
				if (psSME->IbssChan.band == 2)	//5G Hz
				{
					psSME->BasicRateBitmap = LOCAL_11A_BASIC_RATE_BITMAP;
					psSME->OpRateBitmap = LOCAL_11A_OPERATION_RATE_BITMAP;
				}
				else
				{
					psSME->BasicRateBitmap = LOCAL_11B_BASIC_RATE_BITMAP;
					psSME->OpRateBitmap = LOCAL_11B_OPERATION_RATE_BITMAP;
				}
				break;
		}
	}
	//if (psSME->boDUTmode == TRUE)
	// 	psSME->BasicRateBitmap and psSME->OpRateBitmap will be set by DUT IOCTL

	//management frames use basic rate to transmit
	BitMap = psSME->BasicRateBitmap;
	for (BitIndex=0 ; BitIndex<32; BitIndex++)
	{
		if( BitMap & (1<<BitIndex) )
			break;
	}
	psLOCAL->CurrentTxRateForMng = bBitmapToRate(BitIndex);

	i = j = 0;
	for (BitIndex=0 ; BitIndex<32; BitIndex++)
	{
		tmp1 = 1<<BitIndex;
		if (psSME->BasicRateBitmap&tmp1)
			psSME->BSSBasicRateSet[i++] = 0x80 | bBitmapToRate(BitIndex);
		if (psSME->OpRateBitmap&tmp1)
			psSME->OperationalRateSet[j++] = bBitmapToRate(BitIndex);
	}
	psSME->NumOfBSSBasicRate = i;
	psSME->NumOfOperationalRate = j;

	//k = 0;
	DesiredRate2BSSdescriptor( Adapter, psDesData,
							   psSME->BSSBasicRateSet, psSME->NumOfBSSBasicRate,
							   psSME->OperationalRateSet, psSME->NumOfOperationalRate );

	//===================================================================
	//added by WS 05/25/05 for WPA_IE of IBSS beacon
	//TODO: [WKCHEN]-- Is the condition check correct??
	if((psSME->bDesiredAuthMode!=OPEN_AUTH)&&(psSME->bDesiredAuthMode!=SHARE_AUTH))
		AddIBSSIe(Adapter,psDesData);
	//================================================================================================

	MLME_findSTA(psDesData);	//change the state to IDLE_SCAN
	//11G TODO: how about IBSS_Parameter_Set??
	return 1;
}

//======================================================================================================
//added by WS for adding rsn ie for IBSS for WPA_NONE.
void AddIBSSIe(PWB32_ADAPTER Adapter,PWB_BSSDESCRIPTION psDesData)
{
    ULONG RSN_Ver;
    ULONG RSN_Capability;
    ULONG Group_Key_Cipher = 0;
    ULONG Pairwise_Key_Cipher = 0;
    ULONG Authentication_Management_Suite = 0;
    ULONG RSN_IE_OUI;
    ULONG RSN_IE_Type;

	//TODO : WPA2
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("[WS]AddIBSS_IE\n"));
	#endif
	RSN_IE_OUI=OUI_WPA;//bitmap for USB register 07/22/04
	RSN_IE_Type=(ULONG)OUI_WPA_ADDITIONAL;//bitmap for USB register 07/22/04
	RSN_Ver=(ULONG)VERSION_WPA;//bitmap for USB register 07/22/04
    RSN_Capability=0x00000000;
	switch(psSME->encrypt_status)
	{
		case ENCRYPT_WEP://added by WS for WPAN-None 05/25/04
			if(psSME->key_length==5)
			{
				Group_Key_Cipher=0x00000002;//bitmap
				Pairwise_Key_Cipher=(ULONG)0x00000002;//bitmap
			}
			else
			{
				Group_Key_Cipher=(ULONG)0x00000020;//bitmap
				Pairwise_Key_Cipher=(ULONG)0x00000020;//bitmap
			}
			break;
		case ENCRYPT_TKIP:
			Group_Key_Cipher=(ULONG)0x00000004;//bitmap
			Pairwise_Key_Cipher=(ULONG)0x00000001;//bitmap
			break;
		case ENCRYPT_CCMP:
			Group_Key_Cipher=(ULONG)0x00000010;//bitmap
			Pairwise_Key_Cipher=(ULONG)0x00000001;//bitmap
			break;
		default: break;
	}
	switch (psSME->bDesiredAuthMode)
	{
		case WPA_AUTH:
			Authentication_Management_Suite=(ULONG)0x00000002;//bitmap
			break;
		case WPAPSK_AUTH:
			Authentication_Management_Suite=(ULONG)0x00000004;//bitmap
			break;
		case WPANONE_AUTH:
			Authentication_Management_Suite=(ULONG)0x00000001;//bitmap
		break;
			default: break;
	}

	psLOCAL->RSN_IE_Bitmap = 0;//clear the RSN_IE_Bitmap
	psLOCAL->RSN_IE_Bitmap = (RSN_Ver <<29) | (RSN_Capability <<24) |(Group_Key_Cipher <<16)
							 | (Pairwise_Key_Cipher <<8) | (Authentication_Management_Suite << 0);

	psLOCAL->RSN_OUI_Type = (RSN_IE_OUI <<8) | (RSN_IE_Type <<0);

	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("[WS]the RSN_IE_Bitmap=%x\n", psLOCAL->RSN_IE_Bitmap));
	WBDEBUG(("[WS]the RSN_OUI=%x\n", psLOCAL->RSN_OUI_Type));
	#endif
}

void DesiredRate2BSSdescriptor(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData,
							 UCHAR *pBasicRateSet, UCHAR BasicRateCount,
							 UCHAR *pOperationRateSet, UCHAR OperationRateCount)
{
	UCHAR		TmpRateSpace[64];
	UCHAR		TotalRateLen;

	if (BasicRateCount < 20)
		OS_MEMORY_COPY( TmpRateSpace, pBasicRateSet, BasicRateCount );
	if (OperationRateCount < 20)
		OS_MEMORY_COPY( TmpRateSpace + BasicRateCount, pOperationRateSet, OperationRateCount );
	TotalRateLen = BasicRateCount + OperationRateCount;
	psDesData->SupportedRateSet.Element_ID = ELEMENT_ID_SUPPORTED_RATES;
	//Fill the rates of temparary space into the SupportedRate Element. If
	//it is full, fill to the ExtendedSupportedRate Element.
	if (TotalRateLen <= 8)
	{
		OS_MEMORY_COPY( psDesData->SupportedRateSet.SupportedRates, TmpRateSpace, TotalRateLen );
		psDesData->SupportedRateSet.Length = TotalRateLen;
	}
	else
	{
		OS_MEMORY_COPY( psDesData->SupportedRateSet.SupportedRates, TmpRateSpace, 8 );
		psDesData->SupportedRateSet.Length = 8;
		TotalRateLen -= 8;
		psDesData->ExtendedSupportedRateSet.Element_ID = ELEMENT_ID_EXTENDED_SUPPORTED_RATES;
		OS_MEMORY_COPY( psDesData->ExtendedSupportedRateSet.ExtendedSupportedRates, TmpRateSpace+8, TotalRateLen );
		psDesData->ExtendedSupportedRateSet.Length = TotalRateLen;
	}
}

void DesiredRate2InfoElement(PWB32_ADAPTER Adapter, UCHAR *addr, USHORT *iFildOffset,
							 UCHAR *pBasicRateSet, UCHAR BasicRateCount,
							 UCHAR *pOperationRateSet, UCHAR OperationRateCount)
{
	struct  Supported_Rates_Element				*ptr1;
	struct	Extended_Supported_Rates_Element	*ptr2;
	USHORT	FieldOffset;
	UCHAR		TmpRateSpace[64];
	UCHAR		TotalRateLen;

	if( BasicRateCount < 20 )
		OS_MEMORY_COPY( TmpRateSpace, pBasicRateSet, BasicRateCount );

	if( OperationRateCount < 20 )
		OS_MEMORY_COPY( TmpRateSpace + BasicRateCount, pOperationRateSet, OperationRateCount );

	TotalRateLen = BasicRateCount + OperationRateCount;

	FieldOffset = *iFildOffset;
	ptr1 = (struct Supported_Rates_Element *)(addr + FieldOffset);
	ptr1->Element_ID = ELEMENT_ID_SUPPORTED_RATES;
	//Fill the rates of temparary space into the SupportedRate Element. If
	//it is full, fill to the ExtendedSupportedRate Element.
	if (TotalRateLen <= 8)
	{
		OS_MEMORY_COPY( ptr1->SupportedRates, TmpRateSpace, TotalRateLen );
		ptr1->Length = TotalRateLen;
		FieldOffset += (ptr1->Length+2);
	}
	else
	{
		OS_MEMORY_COPY( ptr1->SupportedRates, TmpRateSpace, 8 );
		TotalRateLen -= 8;
		ptr1->Length = 8;
		FieldOffset += (ptr1->Length+2);
		ptr2 = (struct Extended_Supported_Rates_Element *)(addr + FieldOffset);
		ptr2->Element_ID = ELEMENT_ID_EXTENDED_SUPPORTED_RATES;
		OS_MEMORY_COPY( ptr2->ExtendedSupportedRates, TmpRateSpace+8 , TotalRateLen );
		ptr2->Length = TotalRateLen;
		FieldOffset += (ptr2->Length+2);
	}

	*iFildOffset = FieldOffset;
}

void BSSAddIBSSdata(PWB32_ADAPTER Adapter, PWB_BSSDESCRIPTION psDesData)
{
	//USHORT wBssIdx;
	
	// copy the data of connected STA(available from sLocalPara->wConnectedSTAindex)
	// to the new description(local)
	//psLOCAL->wConnectedSTAindex
	//psDesData->bBssType = 
}

// NOTE: return(1) means 'EQ', return(0) means 'NEQ'
BOOL boCmpMacAddr( PUCHAR adr1, PUCHAR adr2 )
{
	return OS_MEMORY_COMPARE( adr1, adr2, MAC_ADDR_LENGTH );
}

BOOL boCmpSSID(struct SSID_Element *psSSID1, struct SSID_Element *psSSID2)
{
	if (psSSID1->Length == psSSID2->Length)
	{
		if( OS_MEMORY_COMPARE( psSSID1->SSID, psSSID2->SSID, psSSID1->Length ) )
			return (1);
	}
	return 0;
}

//============================================================================
// wRoamingQuery --
//
// Description:
//		 For roaming module to find out the candidate AP with the same SSID.
//	 It just chooses the first found AP. It may choose the original connected AP.
//	 If the signal of original AP is lost, this function may choose the original
//	 AP to try to join. If it is the first time that try to re-join to the original
//	 AP, the content of original AP in BSSdescription will not be removed. If this
//	 re-join fails(JoinFail timeout), the content of original AP in BSSdescription
//	 will be removed. If this re-join success, the local device will not do
//	 authentication or association because the content in BSSdescription is still
//	 valid.

// Arguments:
//		Adapter    -   The handle of an adapter bock.
//
// Return:
//		the BSSdescriptor index of the candidate
//============================================================================
USHORT wRoamingQuery(PWB32_ADAPTER Adapter)
{
	USHORT i, candidate = 0;
	LONG	rssi, bestrssi = -300, threshold;
	UCHAR	condition;

	#ifdef _PE_STATE_DUMP_
	UCHAR ssid[33];

	WBDEBUG(("desired SSID len=%x\n",psSME->sDesiredSSID.Length));
	if (psSME->sDesiredSSID.Length != 0)
	{
		OS_MEMORY_COPY( ssid, psSME->sDesiredSSID.SSID, psSME->sDesiredSSID.Length );
		ssid[psSME->sDesiredSSID.Length] = '\0';
		WBDEBUG(("desired SSID=%s\n",ssid));
	}
	#endif

	//It won't roam if using the dedicated BSSID.
	if( !OS_MEMORY_COMPARE( psSME->abDesiredBSSID, "\xff\xff\xff\xff\xff\xff", MAC_ADDR_LENGTH ) )
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("Give up to roam due to the dedicated BSSID\n"));
		#endif
		return 0;
	}

	condition = psLOCAL->RoamStatus;
	threshold = (LONG)(0-psLOCAL->SignalRoamTh);
	for (i=1;i<MAX_BSS_DESCRIPT_ELEMENT;i++)
	{
		if (i == psLOCAL->wConnectedSTAindex )
			continue;
		if (psSME->sDesiredSSID.Length == 0)
		{
			//find the first AP in the descriptor
			if ((boMLME_FoundSTAinfo(psBSS(i))) &&
				(psBSS(i)->bBssType == ESS_NET) &&
				(psSME->_dot11PrivacyInvoked == psBSS(i)->CapabilityInformation.Capability.CF_Privacy))
				return i;
		}
		else if ((boMLME_FoundSTAinfo(psBSS(i))) &&
				(psBSS(i)->bBssType == ESS_NET) &&
				(psBSS(i)->SSID.Length == psSME->sDesiredSSID.Length) &&
				(psSME->_dot11PrivacyInvoked == psBSS(i)->CapabilityInformation.Capability.CF_Privacy))
		{
			if( OS_MEMORY_COMPARE( psBSS(i)->SSID.SSID, psSME->sDesiredSSID.SSID, psSME->sDesiredSSID.Length ) )
			{

				if (!boJoinfilter(Adapter, i))
				{
					#ifdef _PE_STATE_DUMP_
					WBDEBUG(("!!! Join filter in roaming\n"));
					#endif
					continue;
				}

				rssi = hal_get_rssi_bss( &Adapter->sHwData, i, 2);
														 //MAX_ACC_RSSI_COUNT );
				#ifdef _PE_STATE_DUMP_
				WBDEBUG(("preCandidate idx=%d, rssi=%d\n", i, rssi));
				#endif
				switch(condition)
				{
					case 1:
						//if (rssi > -70)
						if (rssi > threshold)
						{
							if (rssi > bestrssi)
							{
								#ifdef _PE_STATE_DUMP_
								WBDEBUG(("Candidate idx=%d\n", i));
								#endif
								candidate = i;
								bestrssi = rssi;
							}
						}
						break;
					case 2:	//can't return 0
						//TODO : choose the best one
						if (rssi > bestrssi)
						{
							#ifdef _PE_STATE_DUMP_
							WBDEBUG(("Candidate idx=%d\n", i));
							#endif
							candidate = i;
							bestrssi = rssi;
						}
						break;
					default:
						break;
				}
			}
		}
	}
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("!!!roam candidate=%d\n", candidate));
	#endif
	//return 0;
	return candidate;
}

//convert the supported and extended supported rate elements to basic and operational
// rates using bit map
void vRateToBitmap(PWB32_ADAPTER Adapter, USHORT index)
{
	int i,j,k;
	UCHAR TmpValue,tmp;

	psBSS(index)->dwBasicRateBitmap = 0;
	psBSS(index)->dwOperationalRateBitmap = 0;
	j = k = 0;
	for (i=0; i<psBSS(index)->SupportedRateSet.Length; i++)
	{
		TmpValue = psBSS(index)->SupportedRateSet.SupportedRates[i];
		if (TmpValue&0x80)
		{	//Basic Rates
			tmp = bRateToBitmapIndex(Adapter, TmpValue&0x7f);
			psBSS(index)->dwBasicRateBitmap |= (1<<tmp);
			psBSS(index)->BasicRate[j++] = TmpValue;
		}
		else
		{
			tmp = bRateToBitmapIndex(Adapter, TmpValue);
			psBSS(index)->dwOperationalRateBitmap |= (1<<tmp);
			psBSS(index)->OperationalRate[k++] = TmpValue;
		}
	}
	for (i=0; i<psBSS(index)->ExtendedSupportedRateSet.Length; i++)
	{
		//Assume the rates in ExtendedSupportedRateSet are all not basic rates
		TmpValue = psBSS(index)->ExtendedSupportedRateSet.ExtendedSupportedRates[i];
		if (TmpValue & 0x80)
		{	//Basic Rates
			tmp = bRateToBitmapIndex(Adapter, TmpValue&0x7f);
			psBSS(index)->dwBasicRateBitmap |= (1<<tmp);
			psBSS(index)->BasicRate[j++] = TmpValue;
		}
		else
		{
			tmp = bRateToBitmapIndex(Adapter, TmpValue);
			psBSS(index)->dwOperationalRateBitmap |= (1<<tmp);
			psBSS(index)->OperationalRate[k++] = TmpValue;
		}
	}
	psBSS(index)->BasicRate[j] = 0;
	psBSS(index)->OperationalRate[k] = 0;
	//Operational rates will include the basic rates to avoid the condition that
	// supported rate element is lack of operational rates.
	//psBSS(index)->dwOperationalRateBitmap |= psBSS(index)->dwBasicRateBitmap;

}

//return the index in the bitmap
UCHAR bRateToBitmapIndex(PWB32_ADAPTER Adapter, UCHAR bRate)
{
	UCHAR	index;	//bit number 0 ~ 31

	if (bRate <= RATE_24M)
		index = bRate >> 1;
	else
		index = (bRate+4) >> 2;
	if (index>31)
		return 0;
	else
		return index;
}

UCHAR bBitmapToRate(UCHAR i)
{
	//i : bit number 0 ~ 31
	if (i>31)
		return 0;
	else
		return (Bitmap2RateValue[i]);
}

BOOL boIsERPsta(PWB32_ADAPTER Adapter, USHORT i)
{
	ULONG tmp;

	//If the STA doesn't include ERP data rates, it belongs to NonERP STA
	tmp = psBSS(i)->dwBasicRateBitmap | psBSS(i)->dwOperationalRateBitmap;
	//clear bit 1, 2, 5.5, 11
	tmp &= 0xfffff7d9;
	if (tmp>0)
		return TRUE;
	else
		return FALSE;
}

BOOLEAN boCheckConnect(PWB32_ADAPTER Adapter)
{
	if ((psLOCAL->wConnectedSTAindex !=0) &&
		(psBSS(psLOCAL->wConnectedSTAindex)->bBssType == IBSS_NET))
	{
		//89C35 H/W can merge automatically.
		//Make sure that the bssid stored in S/W and H/W can be consistent
		hal_get_bssid( &Adapter->sHwData, psLOCAL->HwBssid );
	}
	if (psLOCAL->bConnectFlag == 1)
	{
		psLOCAL->bConnectFlag = 0;
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("Reset Connect flag.\n"));
		#endif
		BssUpToDate(Adapter);
		psSCAN->BssTimeStamp++;
		if (psSCAN->BssTimeStamp == 0xffffffff)	//overflow
			psSCAN->BssTimeStamp = 0;
		return TRUE;
	}
	else
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("Beacon lost!\n"));
		#endif
		return FALSE;
	}
}

BOOLEAN boCheckSignal(PWB32_ADAPTER Adapter)
{
	LONG rssi, threshold;

	rssi = hal_get_rssi_bss( &Adapter->sHwData,
						 		psLOCAL->wConnectedSTAindex,
						 		MAX_ACC_RSSI_COUNT );

	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("Check RSSI =%d!\n", rssi));
	#endif

	threshold = (LONG)(0 - psLOCAL->SignalLostTh);
	//if (rssi < -70)
	if (rssi < threshold)
	{
		#ifdef _PE_STATE_DUMP_
		WBDEBUG(("Signal lost!\n"));
		#endif
		return FALSE;
	}
	return TRUE;
}

//The BSS descriptor will be checked if it is up-to-date when performing background
//scan.
void BssScanUpToDate(PWB32_ADAPTER Adapter)
{
	UCHAR ssid[52];
	USHORT	i;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		//if (i != psLOCAL->wConnectedSTAindex) //If the state is StartIBSS, local descirptor
												//may be cleared.
		if (i != psSME->wDesiredJoinBSS)
		{
			//The  BSS descriptor will be cleared if not receiving any beacon/probe response
			//during 3 minutes or more.
			if (!boMLME_InactiveState(psBSS(i)) &&
				((psSCAN->ScanTimeStamp - psBSS(i)->ScanTimeStamp) >= 3 ))
				//((psSCAN->ScanTimeStamp - psBSS(i)->ScanTimeStamp) >= 2 ))
			{
				OS_MEMORY_COPY( ssid, (UCHAR *)psBSS(i)->SSID.SSID, (UCHAR)psBSS(i)->SSID.Length );
				ssid[psBSS(i)->SSID.Length] = '\0';
				#ifdef _PE_STATE_DUMP_
				WBDEBUG(("*** Clear BSS descriptor due to scan, index=%d, ssid=%s\n", i, ssid));
				#endif
				ClearBSSdescpt(Adapter, i);
			}
		}
	}
}

//The BSS descriptors at the channel that the connection is will be
// checked if they are up-to-date.
void BssUpToDate(PWB32_ADAPTER Adapter)
{
	USHORT	i;
	LONG	interval;

	for (i=2; i<MAX_BSS_DESCRIPT_ELEMENT; i++)
	{
		if (i != psLOCAL->wConnectedSTAindex)
		{
			//The BSS descriptor will be cleared if not receiving any beacon/probe response
			//during ??.
			if (psSCAN->BssTimeStamp == 0)	//overflow occurs, recount
			{
				psBSS(i)->BssTimeStamp = 0;
				continue;
			}
			if (!boMLME_InactiveState(psBSS(i)) &&
				(psBSS(i)->DS_Parameter_Set.Current_Channel ==
							psBSS(psLOCAL->wConnectedSTAindex)->DS_Parameter_Set.Current_Channel))
			{
				interval = psSCAN->BssTimeStamp - psBSS(i)->BssTimeStamp;
				if ((interval >= 5 ) ||
					(interval <= -5))	//It will occur when psSCAN->BssTimeStamp is overflow.
				{
					UCHAR ssid[50];

					OS_MEMORY_COPY( ssid, (UCHAR *)psBSS(i)->SSID.SSID, (UCHAR)psBSS(i)->SSID.Length );
					ssid[psBSS(i)->SSID.Length] = '\0';
					#ifdef _PE_STATE_DUMP_
					WBDEBUG(("*** Clear BSS descriptor, index=%d, ssid=%s\n", i, ssid));
					#endif
					//MLME_initState(psBSS(i));
					ClearBSSdescpt(Adapter, i);
				}
			}
		}
	}
}

//sort rates, mode = 0 :descent
//					 1 :acscent
void RateSort(UCHAR *RateArray, UCHAR num, UCHAR mode)
{
	UCHAR i, j, tmp;

	if(mode)
	{
		for (i=0; i<(num-1); ++i)
		{
			for (j=i+1; j<num; ++j)
			{
				if (RateArray[j] < RateArray[i])
				{
					//swap
					tmp = RateArray[i];
					RateArray[i] = RateArray[j];
					RateArray[j] = tmp;
				}
			}
		}
	}
}

//acscent ,and DSSS rates first and then OFDM rates,
//such as, 1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, ...
void RateReSortForSRate(PWB32_ADAPTER Adapter, UCHAR *RateArray, UCHAR num)
{
	UCHAR i;

	RateSort(RateArray, num, 1);

	for(i=0; i<num; i++)
	{
		if(RateArray[i] == 22)
			break;
	}
	if(i < num) //we need adjust the order of rate list because 11Mbps rate exists
	{
		for(;i>0;i--)
		{
			if(RateArray[i-1] <= 11)
				break;
			RateArray[i] = RateArray[i-1];
		}
		RateArray[i] = 22;
		psLOCAL->NumOfDsssRateInSRate = i+1;
	}
	else
	{
		for(i=0; i<num; i++)
		{
			if (RateArray[i] >= 12)
				break;
		}
		psLOCAL->NumOfDsssRateInSRate = i;
	}
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("Dump Data Rates, no of DSSS rate=%d\n",psLOCAL->NumOfDsssRateInSRate));
	DataDmp(RateArray, num, 0);
	#endif
}

void SetMaxTxRate(PWB32_ADAPTER Adapter)
{
	UCHAR	RateIdx, OfdmRateIdx;

	RateIdx = psLOCAL->NumOfSRate - 1;

	//get the max tx rate
	psLOCAL->CurrentTxRate = psLOCAL->SRateSet[RateIdx];

	//decide the fallback rate : next level with the same modulation type
	#ifdef _USE_FALLBACK_RATE_
	OfdmRateIdx = psLOCAL->NumOfDsssRateInSRate;
	if (RateIdx >= OfdmRateIdx)
	{
		//Current tx rate belongs to OFDM rates
		if (RateIdx != OfdmRateIdx)
			psLOCAL->CurrentTxFallbackRate = psLOCAL->SRateSet[RateIdx-1];
		else
			psLOCAL->CurrentTxFallbackRate = psLOCAL->SRateSet[RateIdx];
	}
	else
	{
		//Current tx rate belongs to DSSS rates
		if (RateIdx > 0)
			psLOCAL->CurrentTxFallbackRate = psLOCAL->SRateSet[RateIdx-1];
		else
			psLOCAL->CurrentTxFallbackRate = psLOCAL->SRateSet[RateIdx];
	}
	#else
	psLOCAL->CurrentTxFallbackRate = psLOCAL->CurrentTxRate;
	#endif
	#ifdef _PE_TX_DUMP_
	WBDEBUG(("Max Tx rate =%d, fallback rate =%d\n",
						psLOCAL->CurrentTxRate,
						psLOCAL->CurrentTxFallbackRate));
	#endif
}



//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//added by ws for add IE to WPA packet  05/15/04
void CreateWpaIE(PWB32_ADAPTER Adapter,
                USHORT* iFildOffset,
                PUCHAR msg,
                struct  Management_Frame* msgHeader,
                struct  Association_Request_Frame_Body* msgBody,
                USHORT  iMSindex)
{
	if ((psSME->bDesiredAuthMode==WPA_AUTH)||(psSME->bDesiredAuthMode==WPAPSK_AUTH))
	{
		UCHAR									    RSN_Element[100];
		struct RSN_Information_Element			UNALIGNED *pRsnWpaElement;
		struct RSN_Auth_Sub_Information_Element	*pRsnWpaSubElement;
		ULONG	OUItmp;
		USHORT	PairwiseKeySuiteCount, AuthKeyMngtSuiteCount; //20061011 add by anson's endian

		OUItmp = cpu_to_le32( OUI_WPA ); //20060926 anson's endian
		pRsnWpaElement = (struct RSN_Information_Element *)RSN_Element;

		#ifdef _PE_TX_DUMP_
		WBDEBUG(("addr of Element_ID =%p\n", 		&pRsnWpaElement->Element_ID));
		WBDEBUG(("addr of Length =%p\n", 			&pRsnWpaElement->Length));
		WBDEBUG(("addr of OuiWPAAdditional =%p\n",	&pRsnWpaElement->OuiWPAAdditional));
		WBDEBUG(("addr of OuiWPAAdditional.Value =%p\n",	&pRsnWpaElement->OuiWPAAdditional.Value));
		WBDEBUG(("addr of Version =%p\n",			&pRsnWpaElement->Version));
		#endif

		pRsnWpaElement->Element_ID = ELEMENT_ID_RSN_WPA;
		OS_MEMORY_COPY( pRsnWpaElement->OuiWPAAdditional.Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA) );
		pRsnWpaElement->OuiWPAAdditional.Value[3] = OUI_WPA_ADDITIONAL;
		pRsnWpaElement->Version = cpu_to_le16( VERSION_WPA ); //20060926 anson's endian
			
        OS_MEMORY_COPY( &pRsnWpaElement->GroupKeySuite, &psBSS(iMSindex)->group_cipher, sizeof(OUI_WPA) );
        /*memcpy(&pRsnWpaElement->PairwiseKeySuite,&psBSS(iMSindex)->pairwise_key_cipher_suites \
                                  ,sizeof(OUI_WPA)* psBSS(iMSindex)->pairwise_key_cipher_suite_count);
        pRsnWpaElement->PairwiseKeySuiteCount=psBSS(iMSindex)->pairwise_key_cipher_suite_count;*/

		OS_MEMORY_COPY( pRsnWpaElement->PairwiseKeySuite[0].Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA) );
        //pRsnWpaElement->PairwiseKeySuite[0].Value[3] =psBSS(iMSindex)->pairwise_key_cipher_suite_selected;
        pRsnWpaElement->PairwiseKeySuite[0].Value[3] =psSME->DesiredEncrypt;
		//only one pairwise suite is allowed,it will be highest priority. 
		//pRsnWpaElement->PairwiseKeySuiteCount =	1; //20061011 marked anson's endian
		PairwiseKeySuiteCount = 1; 
		pRsnWpaElement->PairwiseKeySuiteCount =	cpu_to_le16( PairwiseKeySuiteCount); //20061011 anson's endian
				
		pRsnWpaSubElement = (struct RSN_Auth_Sub_Information_Element *)
								(RSN_Element + sizeof(struct RSN_Information_Element) + 
								   //(pRsnWpaElement->PairwiseKeySuiteCount-1)*(sizeof(SUITE_SELECTOR)));
								   (PairwiseKeySuiteCount-1)*(sizeof(SUITE_SELECTOR)));  //20061011 anson's endian		
		//only one Authentication suite is allowed.
		//pRsnWpaSubElement->AuthKeyMngtSuiteCount = 1; //20061011 marked anson's endian
		AuthKeyMngtSuiteCount = 1;  //20061011 anson's endian
		pRsnWpaSubElement->AuthKeyMngtSuiteCount = cpu_to_le16(AuthKeyMngtSuiteCount); //20061011 anson's endian

		if (psSME->bDesiredAuthMode == WPA_AUTH)
		{
			OS_MEMORY_COPY( pRsnWpaSubElement->AuthKeyMngtSuite[0].Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA) );
			pRsnWpaSubElement->AuthKeyMngtSuite[0].Value[3] = OUI_AUTH_8021X;
		}
		else if (psSME->bDesiredAuthMode == WPAPSK_AUTH)
		{
			OS_MEMORY_COPY( pRsnWpaSubElement->AuthKeyMngtSuite[0].Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA) );
			pRsnWpaSubElement->AuthKeyMngtSuite[0].Value[3] = OUI_AUTH_PSK;
		}
		//pRsnWpaElement->Length = 10 +2+pRsnWpaElement->PairwiseKeySuiteCount*(sizeof(SUITE_SELECTOR))
		//							+2+pRsnWpaSubElement->AuthKeyMngtSuiteCount*(sizeof(SUITE_SELECTOR))
		pRsnWpaElement->Length = 10 +2+PairwiseKeySuiteCount*(sizeof(SUITE_SELECTOR))
									+2+AuthKeyMngtSuiteCount*(sizeof(SUITE_SELECTOR))
									#ifdef NDIS_MINIPORT_DRIVER
									+2;//include capability;
									#else
									;//exclude capability;
									#endif
		//to fill capability
		#ifdef NDIS_MINIPORT_DRIVER
		*(USHORT *)(RSN_Element+pRsnWpaElement->Length) = 0;
        #endif
		OS_MEMORY_COPY( &msg[*iFildOffset], pRsnWpaElement, pRsnWpaElement->Length+2 );
		
		#ifdef _PE_TX_DUMP_
		DataDmp((UCHAR *)pRsnWpaElement, pRsnWpaElement->Length+2, 0);
		#endif

		*iFildOffset += (msg[*iFildOffset+1]+2);

		//Save assocReqVarIE is for OID_802_11_Association_information.
		if (psSME->boReassoc)
		{
			// fixed field length(listen interval+capability+MAC addr) = 10
			psSME->AssocReqVarLen = *iFildOffset - sizeof(struct Management_Frame) - 10;
			OS_MEMORY_COPY( psSME->AssocReqVarIE, msg+sizeof(struct Management_Frame)+10, psSME->AssocReqVarLen );
		}
		else
		{
			// fixed field length(listen interval+capability) = 4
			psSME->AssocReqVarLen = *iFildOffset - sizeof(struct Management_Frame) - 4;
			OS_MEMORY_COPY( psSME->AssocReqVarIE, msg+sizeof(struct Management_Frame)+4, psSME->AssocReqVarLen );
		}	
		#ifdef _PE_TX_DUMP_
		WBDEBUG(("Assoc req Var IE:\n"));
		DataDmp(psSME->AssocReqVarIE, psSME->AssocReqVarLen,0);
		#endif
	}

}

#ifdef _WPA2_
//==========================================================================================
//added by WS for add IE for WPA2 packet 
void CreateRsnIE(PWB32_ADAPTER Adapter,
                USHORT* iFildOffset,
                PUCHAR msg,
                struct  Management_Frame* msgHeader,
                struct  Association_Request_Frame_Body* msgBody,
                USHORT  iMSindex)
   {
                
	if ((psSME->bDesiredAuthMode==WPA2_AUTH)||(psSME->bDesiredAuthMode==WPA2PSK_AUTH))
	{
			
		UCHAR									    RSN_Element[200];
		struct WPA2_RSN_Information_Element	    UNALIGNED *pRsnWpa2Element;
        struct WPA2_RSN_Auth_Sub_Information_Element  *pRsnWpa2SubElement;
        struct RSN_Capability_Element                 *CaPa;
		struct PMKID_Information_Element *            AssoReq_PMKID;
		int index=0;
		ULONG	OUItmp;
		USHORT PairwiseKeySuiteCount, AuthKeyMngtSuiteCount; //20061011 add by anson's endian

		OUItmp = cpu_to_le32( OUI_WPA2 ); //20060926 anson's endian
		pRsnWpa2Element = (struct WPA2_RSN_Information_Element *)RSN_Element;
		
		#ifdef _PE_TX_DUMP_
		WBDEBUG(("addr of Element_ID =%p\n", 		&pRsnWpa2Element->Element_ID));
		WBDEBUG(("addr of Length =%p\n", 			&pRsnWpa2Element->Length));
		WBDEBUG(("addr of Version =%p\n",			&pRsnWpa2Element->Version));
		#endif
		
		pRsnWpa2Element->Element_ID = ELEMENT_ID_RSN_WPA2;//48
		
		pRsnWpa2Element->Version = cpu_to_le16( VERSION_WPA ); //20060926 anson's endian //version_WPA and version_WPA2 are the same.
        OS_MEMORY_COPY( &pRsnWpa2Element->GroupKeySuite, &psBSS(iMSindex)->wpa2_group_cipher, sizeof(OUI_WPA2) );
        /*memcpy(&pRsnWpa2Element->PairwiseKeySuite,&psBSS(iMSindex)->wpa2_pairwise_key_cipher_suites \
                                  ,sizeof(OUI_WPA2)* psBSS(iMSindex)->wpa2_pairwise_key_cipher_suite_count);
        pRsnWpa2Element->PairwiseKeySuiteCount=psBSS(iMSindex)->wpa2_pairwise_key_cipher_suite_count;*/


        OS_MEMORY_COPY( pRsnWpa2Element->PairwiseKeySuite[0].Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA2) );
        pRsnWpa2Element->PairwiseKeySuite[0].Value[3] =psSME->DesiredEncrypt;
        //only one pairwise suite is allowed
		//20061011 anson's endian
		//pRsnWpa2Element->PairwiseKeySuiteCount =1;
		PairwiseKeySuiteCount = 1;
		pRsnWpa2Element->PairwiseKeySuiteCount = cpu_to_le16( PairwiseKeySuiteCount );
				
        index=sizeof(struct WPA2_RSN_Information_Element)+
			        (pRsnWpa2Element->PairwiseKeySuiteCount-1)*(sizeof(SUITE_SELECTOR));
				
        pRsnWpa2SubElement = (struct WPA2_RSN_Auth_Sub_Information_Element *)(RSN_Element + index);
		//20061011 anson's endian
        	//pRsnWpa2SubElement->AuthKeyMngtSuiteCount = 1; 
		AuthKeyMngtSuiteCount = 1;
		pRsnWpa2SubElement->AuthKeyMngtSuiteCount = cpu_to_le16( AuthKeyMngtSuiteCount ); 
		
		if (psSME->bDesiredAuthMode == WPA2_AUTH)
		{
			OS_MEMORY_COPY( pRsnWpa2SubElement->AuthKeyMngtSuite[0].Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA2) );
			pRsnWpa2SubElement->AuthKeyMngtSuite[0].Value[3] = OUI_AUTH_8021X;
		}
		else if (psSME->bDesiredAuthMode == WPA2PSK_AUTH)
		{
			OS_MEMORY_COPY( pRsnWpa2SubElement->AuthKeyMngtSuite[0].Value, (UCHAR *)&OUItmp, sizeof(OUI_WPA2) );
			pRsnWpa2SubElement->AuthKeyMngtSuite[0].Value[3] = OUI_AUTH_PSK;
		}
		
        index+=sizeof(struct WPA2_RSN_Auth_Sub_Information_Element)+
                               //(pRsnWpa2SubElement->AuthKeyMngtSuiteCount-1)*sizeof(SUITE_SELECTOR); 
				(AuthKeyMngtSuiteCount-1)*sizeof(SUITE_SELECTOR);  //20061011 anson's endian
        //Fill capability
        CaPa=(struct RSN_Capability_Element *)(RSN_Element+index);
        //CaPa->wValue=0x0010;
		#ifdef NDIS_MINIPORT_DRIVER
        CaPa->RSN_Capability.Pre_Auth=1;
		#else
        CaPa->RSN_Capability.Pre_Auth=0;
		#endif
		CaPa->RSN_Capability.No_Pairwise=0;
		CaPa->RSN_Capability.PTK_Replay_Counter=00;
		CaPa->RSN_Capability.GTK_Replay_Counter=00;
        CaPa->RSN_Capability.Reserved1=00;
		CaPa->RSN_Capability.Reserved2=0;
		
        index+=sizeof(struct RSN_Capability_Element);
		AssoReq_PMKID=(struct PMKID_Information_Element *)(RSN_Element+index);
        AssoReq_PMKID->PMKID_Count=0; 
        //to find pmkid for desired bssid the NIC is roaming to  
        if(SearchPmkid(Adapter,msgHeader,AssoReq_PMKID))
          {
            //if(AssoReq_PMKID->PMKID_Count >16)
              //  break;
			//20061011 anson's endian
			//pRsnWpa2Element->Length = 6 +2+(pRsnWpa2Element->PairwiseKeySuiteCount* sizeof(SUITE_SELECTOR))
			//							+2+(pRsnWpa2SubElement->AuthKeyMngtSuiteCount* sizeof(SUITE_SELECTOR))
			pRsnWpa2Element->Length = 6 +2+(PairwiseKeySuiteCount* sizeof(SUITE_SELECTOR))
										+2+(AuthKeyMngtSuiteCount* sizeof(SUITE_SELECTOR))
									#ifdef NDIS_MINIPORT_DRIVER
									+2+2+(AssoReq_PMKID->PMKID_Count*sizeof(NDIS_802_11_PMKID_VALUE));
									#else
									//TODO : sizeof(NDIS_802_11_PMKID_VALUE) = ??
									+2+2+(AssoReq_PMKID->PMKID_Count*16); 
									#endif
          }
        else
			//20061011 anson's endian
			//pRsnWpa2Element->Length = 6 +2+(pRsnWpa2Element->PairwiseKeySuiteCount* sizeof(SUITE_SELECTOR))
			//						+2+(pRsnWpa2SubElement->AuthKeyMngtSuiteCount* sizeof(SUITE_SELECTOR))
			pRsnWpa2Element->Length = 6 +2+(PairwiseKeySuiteCount* sizeof(SUITE_SELECTOR))
									+2+(AuthKeyMngtSuiteCount* sizeof(SUITE_SELECTOR))
									    +2;

		//+2 is for Element ID and version Number
		OS_MEMORY_COPY( &msg[*iFildOffset], pRsnWpa2Element, pRsnWpa2Element->Length+2 );

		#ifdef _PE_TX_DUMP_
		DataDmp((UCHAR *)pRsnWpa2Element, pRsnWpa2Element->Length+2, 0);
		#endif

		//added the length of Rsn IE.
		*iFildOffset +=(pRsnWpa2Element->Length+2) ;
		if (psSME->boReassoc)
		{
			// fixed field length(listen interval+capability+MAC addr) = 10
			psSME->AssocReqVarLen = *iFildOffset - sizeof(struct Management_Frame) - 10;
			OS_MEMORY_COPY( psSME->AssocReqVarIE, msg+sizeof(struct Management_Frame)+10, psSME->AssocReqVarLen );
		}
		else
		{
			// "-4" is for capability field and listen interval
			psSME->AssocReqVarLen = *iFildOffset - sizeof(struct Management_Frame) - 4;
			OS_MEMORY_COPY( psSME->AssocReqVarIE, msg+sizeof(struct Management_Frame)+4, psSME->AssocReqVarLen );
		}

		#ifdef _PE_TX_DUMP_
		WBDEBUG(("Assoc req Var IE:\n"));
		DataDmp(psSME->AssocReqVarIE, psSME->AssocReqVarLen,0);
		#endif
	}
	
  }	

USHORT SearchPmkid(PWB32_ADAPTER Adapter,struct  Management_Frame* msgHeader,struct PMKID_Information_Element * AssoReq_PMKID )
{
   ULONG i;
   PMKID_Table *PMKIDTable=(PMKID_Table* )psSME->PmkIdTable;
   for(i=0; i<16;i++)
    {
		if( boCmpMacAddr( PMKIDTable->BSSIDInfo[i].PreAuthBssID, msgHeader->BSSID ) )
        {
			OS_MEMORY_COPY( &(AssoReq_PMKID->pmkid[AssoReq_PMKID->PMKID_Count]),
							&(PMKIDTable->BSSIDInfo[i].pmkid_value),
							sizeof(PMKID) );
          AssoReq_PMKID->PMKID_Count++;
        }
    }
   return AssoReq_PMKID->PMKID_Count;
}
#endif	//end def _WPA2_
